﻿using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using AutoMapper;

namespace Tools
{
    public static   class ExtendsMethod
    {
        
        #region 字符串是否为空

        /// <summary>
        ///     字符串是否为空
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        public static bool IsEmpty(this string s)
        {
            return string.IsNullOrWhiteSpace(s);
        }

        #endregion

        #region 正则表达式 bool IsMatch

        /// <summary>
        ///     指示所指定的正则表达式在指定的输入字符串中是否找到了匹配项。
        /// </summary>
        /// <param name="s"></param>
        /// <param name="pattern"></param>
        /// <returns></returns>
        public static bool IsMatch(this string s, string pattern)
        {
            return s != null && Regex.IsMatch(s, pattern);
        } 
        #endregion

        #region 验证邮箱 IsEmail

        /// <summary>
        ///     验证邮箱
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static bool IsEmail(string source)
        {
            return Regex.IsMatch(source,
                @"^[A-Za-z0-9](([_\.\-]?[a-zA-Z0-9]+)*)@([A-Za-z0-9]+)(([\.\-]?[a-zA-Z0-9]+)*)\.([A-Za-z]{2,})$",
                RegexOptions.IgnoreCase);
        }
        public static bool ToBool(this string value)
        {
            if (string.IsNullOrWhiteSpace(value)) return false;
            return value.ToLower() == "true";
        }

        #endregion
 
        #region string MD5

        /// <summary>
        ///     计算指定字符串的MD5值
        /// </summary>
        /// <param name="key">要计算Hash的字符串</param>
        /// <returns>字符串的Hash</returns>
        public static string MD5(this string key)
        {
            return key.MD5(Encoding.UTF8);
        }

        /// <summary>
        ///     计算指定字符串的MD5值
        /// </summary>
        /// <param name="key">要计算Hash的字符串</param>
        /// <param name="encoding">计算Hash的编码方法</param>
        /// <returns>字符串的Hash</returns>
        public static string MD5(this string key, string encoding)
        {
            return key.MD5(Encoding.GetEncoding(encoding));
        }

        /// <summary>
        ///     计算指定字符串的MD5值
        /// </summary>
        /// <param name="key">要计算Hash的字符串</param>
        /// <param name="encoding">计算Hash的编码方法</param>
        /// <returns>字符串的Hash</returns>
        public static string MD5(this string key, Encoding encoding)
        {
            if (key == null) throw new ArgumentNullException();

            var md5 = System.Security.Cryptography.MD5.Create();
            var has = md5.ComputeHash(encoding.GetBytes(key));
            return BitConverter.ToString(has).Replace("-", "").ToUpper();
        }

        #endregion
         
        #region DataTable互转list ToDataTable  ，ToList

        public static DataTable ToDataTable<T>(this IEnumerable<T> varlist)
        {
            var dtReturn = new DataTable();
            // column names 
            PropertyInfo[] oProps = null;
            if (varlist == null) return dtReturn;
            foreach (var rec in varlist)
            {
                // Use reflection to get property names, to create table, Only first time, others will follow 
                if (oProps == null)
                {
                    oProps = rec.GetType().GetProperties();
                    foreach (var pi in oProps)
                    {
                        var colType = pi.PropertyType;
                        if ((colType.IsGenericType) && (colType.GetGenericTypeDefinition() == typeof(Nullable<>)))
                        {
                            colType = colType.GetGenericArguments()[0];
                        }
                        dtReturn.Columns.Add(new DataColumn(pi.Name, colType));
                    }
                }
                var dr = dtReturn.NewRow();
                foreach (var pi in oProps)
                {
                    dr[pi.Name] = pi.GetValue(rec, null) ?? DBNull.Value;
                }
                dtReturn.Rows.Add(dr);
            }
            return dtReturn;
        }

        public static List<T> ToList<T>(this DataTable table) where T : class, new()
        {
            try
            {
                var list = new List<T>();

                foreach (var row in table.AsEnumerable())
                {
                    var obj = new T();

                    foreach (var prop in obj.GetType().GetProperties())
                    {
                        try
                        {
                            var propertyInfo = obj.GetType().GetProperty(prop.Name);
                            propertyInfo.SetValue(obj, Convert.ChangeType(row[prop.Name], propertyInfo.PropertyType),
                                null);
                        }
                        catch
                        {
                            ;
                        }
                    }

                    list.Add(obj);
                }

                return list;
            }
            catch
            {
                return null;
            }
        }

        #endregion
         
        #region 克隆一个对象 Clone<T>
        /// <summary>
        ///     克隆一个对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="item"></param>
        /// <returns></returns>
        public static T Clone<T>(this object item)
        {
            if (item == null) return default(T);
            var formatter = new BinaryFormatter();
            var stream = new MemoryStream();
            formatter.Serialize(stream, item);
            stream.Seek(0, SeekOrigin.Begin);
            var result = (T)formatter.Deserialize(stream);
            stream.Close();
            return result;
        }

        #endregion

        #region 对象转json字符串 ToJson ToObject

        /// <summary>
        /// 对象转 json
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="item"></param>
        /// <returns></returns>
        public static string ToJson(this object item)
        {
            if (item == null) return "";
            string str = Newtonsoft.Json.JsonConvert.SerializeObject(item);
            return str;
        }

        /// <summary>
        ///  json 字符串转 obj
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="item"></param>
        /// <returns></returns>
        public static T ToObject<T>(this string item)
        {
            if (item == null) return default(T);
            T str = Newtonsoft.Json.JsonConvert.DeserializeObject<T>(item);
            return str;
        }

        #endregion

        #region MapTo   类型映射

        /// <summary>
        ///  类型映射,默认字段名字一一对应   Address address = dto.MapTo<Address,AddressDto>();
        /// </summary>
        /// <typeparam name="TDestination">转化之后的对象</typeparam>
        /// <typeparam name="TSource">要被转化的实体</typeparam>
        /// <param name="source">可以使用这个扩展方法的类型，任何引用类型</param>
        /// <returns>转化之后的实体</returns>
        public static TDestination MapTo<TDestination, TSource>(this TSource source)
            where TDestination : class
            where TSource : class
        {
            if (source == null) return default(TDestination);
            var config = new MapperConfiguration(cfg => cfg.CreateMap<TSource, TDestination>());
            var mapper = config.CreateMapper();
            return mapper.Map<TDestination>(source);

        }

        /// <summary>
        /// 集合列表类型映射,默认字段名字一一对应
        /// </summary>
        /// <typeparam name="TDestination">转化之后的对象</typeparam>
        /// <typeparam name="TSource">要被转化的实体</typeparam>
        /// <param name="source">可以使用这个扩展方法的类型，任何引用类型</param>
        /// <returns>转化之后的实体列表</returns>
        public static IEnumerable<TDestination> MapToList<TSource, TDestination>(this IEnumerable<TSource> source)
            where TDestination : class
            where TSource : class
        {
            if (source == null) return new List<TDestination>();
            var config = new MapperConfiguration(cfg => cfg.CreateMap<TSource, TDestination>());
            var mapper = config.CreateMapper();
            return mapper.Map<List<TDestination>>(source);
        }
        #endregion

        #region int ToInt

        /// <summary>
        /// 转成Int
        /// </summary>
        /// <param name="n"></param>
        /// <returns></returns>
        public static int ToInt(this string n)
        {
            if (string.IsNullOrEmpty(n))
            {
                return 0;
            }
            else
            {
                int i = 0;
                int.TryParse(n, out i);

                return i;
            }
        } 
        #endregion



    }


}
